#include <iostream>
using namespace std;


// //饿汉模式---定义类的时候创建单例对象
// //定义一个单例模式的任务队列
// class TaskQueue
// {
// public:
//     static TaskQueue* getInstance(){
//         return m_taskQ;
//     }
//     void print(){
//         cout << "我是单例对象的一个成员函数...." << endl;
//     }
// private:
//     TaskQueue(){};
//     TaskQueue(const TaskQueue& t) = default;
//     TaskQueue& operator=(const TaskQueue& t) = default;
//     ~TaskQueue(){};
//     //只能通过类名访问静态属性或方法
//     static TaskQueue* m_taskQ;

// };
// TaskQueue* TaskQueue::m_taskQ = new TaskQueue;//饿汉模式，在定义类的时候就已经创建了单例对象，会造成资源浪费，因为这个时候还没有人使用单例对象，但是这个对象已经被创建出来了



#include <mutex>
#include <atomic>

// //使用双重检查锁定+原子变量解决多线程下懒汉模式的线程安全问题
// //懒汉模式---什么时候使用单例对象，在使用的时候再去创建对应的实例
// class TaskQueue
// {
// public:
//     static TaskQueue* getInstance(){
//         TaskQueue* task = m_taskQ.load();
//         //锁是为了在多线程的时候线程安全，只保证一个单例对象
//         if(task == nullptr){//双重检查锁定，可以提高效率，只会有一个线程加锁创建对象，其他线程在判读指针不为空就走了
//             m_mutex.lock();
//             task = m_taskQ.load();
//             if(task == nullptr){
//                 task = new TaskQueue;
//                 m_taskQ.store(task);
//             }
//             m_mutex.unlock();
//         }
//         return task;
//     }
//     void print(){
//         cout << "我是单例对象的一个成员函数...." << endl;
//     }
// private:
//     TaskQueue(){};
//     TaskQueue(const TaskQueue& t) = default;
//     TaskQueue& operator=(const TaskQueue& t) = default;
//     // ~TaskQueue(){};
//     //只能通过类名访问静态属性或方法
//     // static TaskQueue* m_taskQ;
//     static mutex m_mutex;
//     static atomic<TaskQueue*> m_taskQ;//用原子变量保存实例对象
// };
// // TaskQueue* TaskQueue::m_taskQ = nullptr;//懒汉模式，在定义类的时候没有创建对象，只在使用的时候创建对象
// atomic<TaskQueue*> TaskQueue::m_taskQ;
// mutex TaskQueue::m_mutex;



//使用静态的局部对象解决线程安全问题-----前提：编译器必须支持c++11
//c++11有如下规定，并且这个操作是在编译时由编译器保证的
//如果指令逻辑进入一个未被初始化的声明遍历，所有并发执行应当等待变量完成初始化
//懒汉模式---什么时候使用单例对象，在使用的时候再去创建对应的实例
class TaskQueue
{
public:
    static TaskQueue* getInstance(){
        static TaskQueue task;
        return &task;
    }
    void print(){
        cout << "我是单例对象的一个成员函数...." << endl;
    }
private:
    TaskQueue(){};
    TaskQueue(const TaskQueue& t) = default;
    TaskQueue& operator=(const TaskQueue& t) = default;
    // ~TaskQueue(){};
    //只能通过类名访问静态属性或方法
};




int main()
{
    TaskQueue* taskQ = TaskQueue::getInstance();
    taskQ->print();

    // TaskQueue t1;
    // TaskQueue t2(taskQ);
    // TaskQueue t3 = taskQ;
    TaskQueue* q = taskQ;//q是指针，q和taskQ指向同一个单例对象
    q->print();
    return 0;
}